import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collections;
import java.util.Vector;


public class IndiceVetorial {
	
	public Vector<NoIndice> ConjuntoNo;
	public boolean IndicePrimario;
	public int IdColuna;
	
	public IndiceVetorial(int idColuna, ArquivoFormato arquivo) throws IOException
	{
		this.IdColuna = idColuna;
		this.IndicePrimario = idColuna == Configuracao.ColunaIndicePrimario;
		
		this.ConjuntoNo = null;
				
		this.LerIndiceArquivo();
		
		if(this.ConjuntoNo == null)
		{
			this.CriarIndice(arquivo, idColuna);
		}
	}
	
	private String GerarNomeArquivo()
	{
		String nomeArquivo = Configuracao.NomeArquivoIndice + this.IdColuna + Configuracao.ExtensaoArquivoIndice;  

		return nomeArquivo; 
	}
	
	private void GravarIndiceArquivo() throws IOException
	{
		String nomeArquivo = this.GerarNomeArquivo();
		nomeArquivo = Configuracao.PathIndice + nomeArquivo;
		
		File file = new File(nomeArquivo);
		
		if(file.exists())
		{
			file.delete();
		}
				
		BufferedWriter br = new BufferedWriter(new FileWriter(new File(nomeArquivo)));
		String linha = null;
		
		for(int cont = 0; cont < this.ConjuntoNo.size(); cont++)
		{
			linha = Configuracao.pad( ConjuntoNo.get(cont).IdIndice, Configuracao.TamanhoRegistroIndice, ' ');
			linha += Configuracao.pad( ConjuntoNo.get(cont).Endereco, Configuracao.TamanhoRegistroIndice, ' ');
			linha += Configuracao.pad( ConjuntoNo.get(cont).Deletado ? Configuracao.FlagDeletado : " ", Configuracao.TamanhoRegistroIndice, ' ');
			linha += '\n';
			
			br.write(linha);
		}
		  
		br.close();  
	}
	
	private void LerIndiceArquivo()
	{
		String nomeArquivo = this.GerarNomeArquivo();
		nomeArquivo = Configuracao.PathIndice + nomeArquivo;
		String linha = null;
		int posicaoInicial = 0;
		int posicaoFinal = 0;
		String idIndice, endereco;
		boolean numerico;
		
		try
		{
			File file = new File(nomeArquivo);
			
			if(file.exists())
			{
				BufferedReader in = new BufferedReader(new FileReader(nomeArquivo));
				
				this.ConjuntoNo = new Vector<NoIndice>();
		    
			    while ((linha = in.readLine()) != null) 
			    {
			    	posicaoInicial = 0;
			    	posicaoFinal = Configuracao.TamanhoRegistroIndice;
			    	
			    	idIndice = linha.substring(posicaoInicial,posicaoFinal);
			    	
			    	posicaoInicial = posicaoFinal;
			    	posicaoFinal = posicaoInicial + Configuracao.TamanhoRegistroIndice;
			    	
			    	endereco = linha.substring(posicaoInicial,posicaoFinal);
			    	
			    	posicaoInicial = posicaoFinal;
			    	posicaoFinal = posicaoInicial + Configuracao.TamanhoRegistroIndice;
			    	
			    	if(this.IdColuna == Configuracao.IdColunaClasse || this.IdColuna == Configuracao.IdColunaDescricao)
			    	{
			    		numerico = false;
			    	}
			    	else
			    	{
			    		numerico = true;
			    	}
			    	
			    	NoIndice no = new NoIndice(idIndice.trim(), endereco.trim(),numerico, Configuracao.VerificarRegistroDeletado(linha));
			    	
			    	this.ConjuntoNo.add(no);
    	
			    }
			    in.close();
			}
		}
		catch(Exception ex)
		{
			ex = ex;
		}
 
	}
	
	public String BuscarEnderecoChave(String valorChave)
	{
		String retorno = "-1";
		int posicao;
		NoIndice indice = new NoIndice(valorChave, null, Configuracao.ValidarInteiro(valorChave), false);
		
		posicao = Collections.binarySearch(ConjuntoNo,indice);
		
		if(posicao >= 0)
		{
			retorno = ConjuntoNo.get(posicao).Endereco; 
		}
		
		return retorno;
	}
	
	private void Ordernar()
	{
		if(ConjuntoNo != null)
		{
			Collections.sort(ConjuntoNo);
		}
	}
	
	private void CriarIndice(ArquivoFormato arquivo, int idColuna) throws IOException
	{
		String valor = null;
		String endereco = null;
		boolean numerico;

		if(arquivo != null)
		{
			if(arquivo.Colunas != null && !arquivo.Colunas.isEmpty())
			{
				this.IdColuna = idColuna;
				
				ConjuntoNo = new Vector<NoIndice>();
				
				IndicePrimario = arquivo.Colunas.get(idColuna).ChavePrimaria;
				
				for(int cont = 0 ; cont < arquivo.Linhas.size(); cont ++)
				{
					Registro reg = arquivo.Linhas.get(cont);
				
					valor = reg.Campos.get(idColuna).Valor;
					
					numerico = reg.Campos.get(idColuna).Coluna.Numerica;
					
					if(IndicePrimario)
					{
						endereco = Long.toString(reg.EnderecoInicio);						
					}
					else
					{
						endereco = reg.Campos.get(0).Valor;
					}
					
					this.ConjuntoNo.add(new NoIndice(valor,endereco,numerico, reg.Deletado));
				}
				
				this.Ordernar();
				
				GravarIndiceArquivo();
			}
		}
	}
	
	public boolean RemoverChave(Campo campo)
	{
		
		return false;
	}

	public boolean InserirChave(Campo campo, String enderecoNovo) 
	{
		String endereco;
		NoIndice novoNo;
		boolean registroInserido = false;
		boolean numerico;
		
		if(campo.Coluna.IdColuna == this.IdColuna)
		{
	    	if(campo.Coluna.IdColuna == Configuracao.IdColunaClasse || campo.Coluna.IdColuna == Configuracao.IdColunaDescricao)
	    	{
	    		numerico = false;
	    	}
	    	else
	    	{
	    		numerico = true;
	    	}
	    	
			if(this.IndicePrimario)
			{
				endereco = this.BuscarEnderecoChave(campo.Valor);
				
				if(endereco != "-1")
				{
					novoNo = new NoIndice(campo.Valor, enderecoNovo, numerico, false);
					
					ConjuntoNo.add(novoNo);
					
					registroInserido = true;
				}
				else
				{
					registroInserido = false;
				}
			}
			else
			{
				novoNo = new NoIndice(campo.Valor, enderecoNovo, numerico, false);
				
				registroInserido = true;
			}
		}

		return registroInserido;
	}
}

